﻿using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Color = Microsoft.Xna.Framework.Color;
using Matrix = Microsoft.Xna.Framework.Matrix;

namespace Babylon.Toolbox
{
    public class SplattingEffect : ModelEffect
    {
        readonly EffectParameter _uvFactorParameter;
        
        readonly EffectParameter worldViewProjectionParameter;
        readonly EffectParameter worldParameter;
        readonly EffectParameter booleans01Parameter;
        readonly EffectParameter diffuseColorParameter;
        readonly EffectParameter emissiveColorParameter;
        readonly EffectParameter ambientColorParameter;
        readonly EffectParameter lightPositionParameter;

        readonly SamplerState samplerState;

        public SplattingEffect (GraphicsDevice device)
            :base(device, "Babylon.Toolbox", "Effects/SplattingEffect/SplattingEffect")
        {
            _uvFactorParameter = GetParameter("UVFactor");
            UVFactor = new Vector2(1,1);

            worldViewProjectionParameter = GetParameter("WorldViewProjection");
            worldParameter = GetParameter("World");
            diffuseColorParameter = GetParameter("DiffuseColor");
            emissiveColorParameter = GetParameter("EmissiveColor");
            ambientColorParameter = GetParameter("AmbientColor");
            booleans01Parameter = GetParameter("Booleans01");
            lightPositionParameter = GetParameter("LightPosition");

            samplerState = new SamplerState
            {
                AddressU = TextureAddressMode.Wrap,
                AddressV = TextureAddressMode.Wrap,
                AddressW = TextureAddressMode.Wrap,
                Filter = TextureFilter.Linear
            };

            Alpha = 1.0f;
        }

        public string Name { get; set; }

        public override Matrix World { get; set; }
        public override Matrix View { get; set; }
        public override Matrix Projection { get; set; }

        public Color DiffuseColor { get; set; }
        public Texture2D DiffuseTexture { get; set; }

        public Color AmbientColor { get; set; }
        public Color SceneAmbientColor { get; set; }

        public Color EmissiveColor { get; set; }


        public Texture2D BumpTexture { get; set; }

        public Vector3 LightPosition { get; set; }

        public float Alpha { get; set; }

        public Vector2 UVFactor { get; set; }
        public Texture2D AlphaChannelsTexture { get; set; }
        public Texture2D RedChannelTexture { get; set; }
        public Texture2D GreenChannelTexture { get; set; }
        public Texture2D BlueChannelTexture { get; set; }

        public override void Apply()
        {
            _uvFactorParameter.SetValue(new Vector4(UVFactor, 0, 0));
            Device.Textures[3] = AlphaChannelsTexture;
            Device.Textures[4] = RedChannelTexture;
            Device.Textures[5] = GreenChannelTexture;
            Device.Textures[6] = BlueChannelTexture;
            Device.SamplerStates[3] = samplerState;
            Device.SamplerStates[4] = samplerState;
            Device.SamplerStates[5] = samplerState;
            Device.SamplerStates[6] = samplerState;
            Vector4 booleans01 = Vector4.Zero;

            worldViewProjectionParameter.SetValue(World * View * Projection);
            worldParameter.SetValue(World);

            emissiveColorParameter.SetValue(EmissiveColor);
            ambientColorParameter.SetValue(AmbientColor.Multiply(SceneAmbientColor));

            lightPositionParameter.SetValue(LightPosition);

            if (DiffuseTexture != null)
            {
                Device.Textures[0] = DiffuseTexture;
                Device.SamplerStates[0] = samplerState;
                booleans01.X = 1.0f;
                diffuseColorParameter.SetValue(Color.White, Alpha);
            }
            else
            {
                diffuseColorParameter.SetValue(DiffuseColor, Alpha);
            }

            if (BumpTexture != null)
            {
                Device.Textures[1] = BumpTexture;
                Device.SamplerStates[1] = samplerState;
                booleans01.Y = 1.0f;
            }


            booleans01Parameter.SetValue(booleans01);

            base.Apply();
        }
    }
}
